/*********************************** (C) COPYRIGHT ******************************
 * address: https://gitee.com/liuniansihuo/multitasks-os
 *
 * Change Logs:
 * Date			Author      	Notes
 * 2017-04-19	LiuHuo			first version
 *
*******************************************************************************/

#ifndef __Sys_service_H_
#define __Sys_service_H_

//每个任务都会用到以下文件,且只在任务文件中包含该头文件
#include "Typedef.h"
#include "task_def.h"
#include "os_tick.h"
#include "os.h"

//OS版本号，
#define OS_VERSION_MAIN     1u
#define OS_VERSION_SUB      2u


struct task_s
{
    E_TASKID ID;
    task_stat_e state;
    SysTick_t TaskTime;
    void (*run)(void);
    void (*sleep_init)(void);
	void (*msg_process)(E_DATAID , const u32 );
    void (*task_tick)(void);
    void (*task_init)(void);
    unsigned char is_used;

};

#define TASK_DEFAULT_INIT() {.ID=TASKID_MAX,.state=TASK_STAT_NOT_EXIST,.task_init=NULL,}

//任务级函数进行修饰，或特殊函数进行修饰
#define CONSTRUCTOR_DEFAUTL()	__attribute__((constructor))
#define CONSTRUCTOR_LEVEL(x)	__attribute__((constructor(x)))


/**************************************************************
*							任务消息
*说明：
* 消息发送接收，必须必须必须  一一对应且数据类型要相同
* 发送数据或地址使用 MSG(...) ，接收数据使用 MSG_D(...)；接收地址并解析数据使用 MSG_P(...)
* 例如： MSG(test0,test1,test2) -> MSG_D(rtest0,rtest1,rtest2) :执行后 rtest0=test0；rtest1=test1；rtest2=test2；
        说明：这种方式不能传递浮点型数据
* 例如： MSG(&test0,&test1,&test2,&test3,&test4,&test5) -> MSG_P(rtest0,rtest1,rtest2,rtest3,rtest4,rtest5)
        执行后：rtest0=test0；rtest1=test1；rtest2=test2；rtest3=test3；rtest4=test4；rtest5=test5；
*
***************************************************************/
#define _MSG_1(x)		            (uc32)(x)
#define _MSG_2(x, y)		        (uc32)(uc32[]){(uc32)(x), (uc32)(y)}
#define _MSG_3(x, y, z)		        (uc32)(uc32[]){(uc32)(x), (uc32)(y), (uc32)(z)}
#define _MSG_4(x, y, z, u)	        (uc32)(uc32[]){(uc32)(x), (uc32)(y), (uc32)(z), (uc32)(u)}
#define _MSG_5(x, y, z, u, v)	    (uc32)(uc32[]){(uc32)(x), (uc32)(y), (uc32)(z), (uc32)(u), (uc32)(v)}
#define _MSG_6(x, y, z, u, v, w)    (uc32)(uc32[]){(uc32)(x), (uc32)(y), (uc32)(z), (uc32)(u), (uc32)(v), (uc32)(w)}
/******************************************************************************************/
#define _MSG_VD0(var,D)		do{var = ((typeof(var))(((uc32*)(D))[0]));}while(0)
#define _MSG_VD1(var,D)		do{var = ((typeof(var))(((uc32*)(D))[1]));}while(0)
#define _MSG_VD2(var,D)		do{var = ((typeof(var))(((uc32*)(D))[2]));}while(0)
#define _MSG_VD3(var,D)		do{var = ((typeof(var))(((uc32*)(D))[3]));}while(0)
#define _MSG_VD4(var,D)		do{var = ((typeof(var))(((uc32*)(D))[4]));}while(0)
#define _MSG_VD5(var,D)		do{var = ((typeof(var))(((uc32*)(D))[5]));}while(0)

#define _MSG_D2(var1,D)                             do{var1 = (typeof(var1))(D);}while(0)
#define _MSG_D3(var1,var2,D)                        _MSG_VD0(var1,D);_MSG_VD1(var2,D)
#define _MSG_D4(var1,var2,var3,D)                   _MSG_VD0(var1,D);_MSG_VD1(var2,D);_MSG_VD2(var3,D)
#define _MSG_D5(var1,var2,var3,var4,D)              _MSG_VD0(var1,D);_MSG_VD1(var2,D);_MSG_VD2(var3,D);_MSG_VD3(var4,D)
#define _MSG_D6(var1,var2,var3,var4,var5,D)         _MSG_VD0(var1,D);_MSG_VD1(var2,D);_MSG_VD2(var3,D);_MSG_VD3(var4,D);_MSG_VD4(var5,D)
#define _MSG_D7(var1,var2,var3,var4,var5,var6,D)    _MSG_VD0(var1,D);_MSG_VD1(var2,D);_MSG_VD2(var3,D);_MSG_VD3(var4,D);_MSG_VD4(var5,D);_MSG_VD5(var6,D)
/******************************************************************************************/
#define _MSG_PD0(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[0]));}while(0)
#define _MSG_PD1(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[1]));}while(0)
#define _MSG_PD2(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[2]));}while(0)
#define _MSG_PD3(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[3]));}while(0)
#define _MSG_PD4(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[4]));}while(0)
#define _MSG_PD5(var,D)		do{var = *((typeof(var)*)(((uc32*)(D))[5]));}while(0)

#define _MSG_P2(var1,D)                             do{var1 = *((typeof(var)*)(D));}while(0)
#define _MSG_P3(var1,var2,D)                        _MSG_PD0(var1,D);_MSG_PD1(var2,D)
#define _MSG_P4(var1,var2,var3,D)                   _MSG_PD0(var1,D);_MSG_PD1(var2,D);_MSG_PD2(var3,D)
#define _MSG_P5(var1,var2,var3,var4,D)              _MSG_PD0(var1,D);_MSG_PD1(var2,D);_MSG_PD2(var3,D);_MSG_PD3(var4,D)
#define _MSG_P6(var1,var2,var3,var4,var5,D)         _MSG_PD0(var1,D);_MSG_PD1(var2,D);_MSG_PD2(var3,D);_MSG_PD3(var4,D);_MSG_PD4(var5,D)
#define _MSG_P7(var1,var2,var3,var4,var5,var6,D)    _MSG_PD0(var1,D);_MSG_PD1(var2,D);_MSG_PD2(var3,D);_MSG_PD3(var4,D);_MSG_PD4(var5,D);_MSG_PD5(var6,D)
/******************************************************************************************/
#define _MSG_RP0(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[0])) = var;}while(0)
#define _MSG_RP1(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[1])) = var;}while(0)
#define _MSG_RP2(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[2])) = var;}while(0)
#define _MSG_RP3(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[3])) = var;}while(0)
#define _MSG_RP4(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[4])) = var;}while(0)
#define _MSG_RP5(var,D)     do{ *((typeof(var)*)(((uc32*)(D))[5])) = var;}while(0)

#define _MSG_R2(var1,D)                             do{ *((typeof(var)*)(D)) = var1;}while(0)
#define _MSG_R3(var1,var2,D)                        _MSG_RP0(var1,D);_MSG_RP1(var2,D);
#define _MSG_R4(var1,var2,var3,D)                   _MSG_RP0(var1,D);_MSG_RP1(var2,D);_MSG_RP2(var3,D);
#define _MSG_R5(var1,var2,var3,var4,D)              _MSG_RP0(var1,D);_MSG_RP1(var2,D);_MSG_RP2(var3,D);_MSG_RP3(var4,D);
#define _MSG_R6(var1,var2,var3,var4,var5,D)         _MSG_RP0(var1,D);_MSG_RP1(var2,D);_MSG_RP2(var3,D);_MSG_RP3(var4,D);_MSG_RP4(var5,D);
#define _MSG_R7(var1,var2,var3,var4,var5,var6,D)    _MSG_RP0(var1,D);_MSG_RP1(var2,D);_MSG_RP2(var3,D);_MSG_RP3(var4,D);_MSG_RP4(var5,D);_MSG_RP5(var6,D);
/******************************************************************************************/

//设置数据指针
#define POINT_SET(p,ID)			sys_task_point_set(ID,(void*)p)

//获取类型指针并赋值,var是指针变量
#define POINT_VPGET(var,ID)		do{var = ((typeof(var))sys_task_point_get(ID));}while(0)

//获取数据并赋值，var是数据变量
#define POINT_VGET(var,ID)		do{var = *((typeof(var)*)sys_task_point_get(ID));}while(0)

//获取类型指针，指定指针类型,T为指针类型。比如:POINT_PGET(u32 *,ID)
#define POINT_PGET(T,ID) 		((const T)sys_task_point_get(ID))

//获取类型数据，指定数据类型，T为数据类型。比如：POINT_GET(u32,ID)
#define POINT_GET(T,ID)			(*((const T*)sys_task_point_get(ID)))


/**************************************************************
*							函数声明
***************************************************************/

unsigned char sys_task_add(const struct task_s * task);
unsigned char  sys_task_del(E_TASKID id);
void sys_msg_process(E_DATAID DatID,  const u32  data ,E_TASKID id);
u8 sys_msg_send(E_DATAID DatID,  const u32  data ,u32 num,...);
task_stat_e sys_task_state_get(E_TASKID id);
void sys_task_state_set(E_TASKID id,task_stat_e state);
void sys_loop_flag_set(u8 flag);
void sys_main(void);

void sys_task_point_set(E_DATAID ID,const void * p);
const void * sys_task_point_get(E_DATAID ID);


/*******************************任务消息发送和接收处理宏定义*****************************
 * 任务消息发送函数统一使用该宏定义。
 * 例如 msg_send(DATID_NULL,MSG(0,1,3),TASKID_SYS,TASKID_XXX)
*/


#define msg_send(DatID,data, ...) do{if(VA_NUM_ARGS(__VA_ARGS__)==1) \
                                        if(GET_VA_ARG_1(__VA_ARGS__) == TASKID_MAX)\
                                            sys_msg_send(DatID, data ,TASKID_MAX);\
                                        else\
                                            sys_msg_process(DatID, data ,GET_VA_ARG_1(__VA_ARGS__)); \
                                    else \
                                        sys_msg_send(DatID, data ,VA_NUM_ARGS(__VA_ARGS__),__VA_ARGS__);\
                                    }while(0)

#define msg_recv(DatID,data,id) do{sys_msg_process(DatID, data ,id);}while(0)


#define MSG(...)          CONNECT2(_MSG_,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
#define MSG_D(...)        CONNECT2(_MSG_D,VA_NUM_ARGS(__VA_ARGS__,data))(__VA_ARGS__,data)
#define MSG_P(...)        CONNECT2(_MSG_P,VA_NUM_ARGS(__VA_ARGS__,data))(__VA_ARGS__,data)
#define MSG_R(...)        CONNECT2(_MSG_R,VA_NUM_ARGS(__VA_ARGS__,data))(__VA_ARGS__,data)

#endif





